﻿//==============================================================================
// File: MarkupExtensionManager.cs
// Created: 2010-06-07
// Author: Piotr Włodek, Arkadiusz Świerczek
//==============================================================================
// This file is a part of MAMMOTH project.
// Copyright (C) 2010 AGH University of Science and Technology, Krakow.
// https://caribou.iisg.agh.edu.pl/trac/mammoth
//
// Mammoth is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Mammoth is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with Mammoth. If not, see http://www.gnu.org/licenses/.
//==============================================================================

using System.Collections.Generic;

namespace WpfRcp.Core.Common.Localization
{
    /// <summary>
    /// Defines a class for managing <see cref="ManagedMarkupExtension"/> objects
    /// </summary>
    /// <remarks>
    /// This class provides a single point for updating all markup targets that use the given Markup 
    /// Extension managed by this class.   
    /// </remarks>
    public class MarkupExtensionManager
    {
        #region Member Variables

        /// <summary>
        /// List of active extensions
        /// </summary>
        private List<ManagedMarkupExtension> m_Extensions = new List<ManagedMarkupExtension>();

        /// <summary>
        /// The number of extensions added since the last cleanup
        /// </summary>
        private int m_CleanupCount;

        /// <summary>
        /// The interval at which to cleanup and remove extensions
        /// </summary>
        private readonly int m_CleanupInterval = 40;

        #endregion

        #region Public Interface

        /// <summary>
        /// Create a new instance of the manager
        /// </summary>
        /// <param name="cleanupInterval">
        /// The interval at which to cleanup and remove extensions associated with garbage
        /// collected targets.  This specifies the number of new Markup Extensions that are
        /// created before a cleanup is triggered
        /// </param>
        public MarkupExtensionManager(int cleanupInterval)
        {
            m_CleanupInterval = cleanupInterval;
        }

        /// <summary>
        /// Force the update of all active targets that use the markup extension
        /// </summary>
        public virtual void UpdateAllTargets()
        {
            foreach (ManagedMarkupExtension extension in m_Extensions)
            {
                extension.UpdateTarget();
            }
        }

        /// <summary>
        /// Return a list of the currently active extensions
        /// </summary>
        public List<ManagedMarkupExtension> ActiveExtensions
        {
            get { return m_Extensions; }
        }

        /// <summary>
        /// Cleanup references to extensions for targets which have been garbage collected.
        /// </summary>
        /// <remarks>
        /// This method is called periodically as new <see cref="ManagedMarkupExtension"/> objects 
        /// are registered to release <see cref="ManagedMarkupExtension"/> objects which are no longer 
        /// required (because their target has been garbage collected).  This method does
        /// not need to be called externally, however it can be useful to call it prior to calling
        /// GC.Collect to verify that objects are being garbage collected correctly.
        /// </remarks>
        public void CleanupInactiveExtensions()
        {
            var newExtensions = new List<ManagedMarkupExtension>(m_Extensions.Count);
            foreach (ManagedMarkupExtension ext in m_Extensions)
            {
                if (ext.IsTargetAlive)
                {
                    newExtensions.Add(ext);
                }
            }
            m_Extensions = newExtensions;
        }

        /// <summary>
        /// Register a new extension and remove extensions which reference target objects
        /// that have been garbage collected
        /// </summary>
        /// <param name="extension">The extension to register</param>
        internal void RegisterExtension(ManagedMarkupExtension extension)
        {
            // Cleanup extensions for target objects which have been garbage collected
            // for performance only do this periodically
            //
            if (m_CleanupCount > m_CleanupInterval)
            {
                CleanupInactiveExtensions();
                m_CleanupCount = 0;
            }
            m_Extensions.Add(extension);
            m_CleanupCount++;
        }

        #endregion
    }
}